/*
 * Copyright 2018 The JA-SIG Collaborative. All rights reserved.
 * distributed with thi file and available online at
 */
package com.lap.scp.admin.config;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import com.lap.scd.commons.core.exception.ManagerException;

/**
 * <pre>
 * 事务控制配置
 * </pre>
 * 
 * @author 劳水生 Exp
 * @Date 2018年2月21日 上午10:01:48
 * @since 1.0
 */
@Configuration
public class TxAutoConfig {
	/**
	 * 拦截表达式
	 */
	private static final String EXPRE = "execution(public * com.lap.scp.*.core.impl.*Manager.*(..))";

	@Bean("txSource")
	public TransactionAttributeSource transactionAttributeSource() {
		NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
		
		RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
		readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
		readOnlyTx.setReadOnly(true);

		RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(
				TransactionDefinition.PROPAGATION_REQUIRED,
				Collections.singletonList(new RollbackRuleAttribute(ManagerException.class)));
		requiredTx.setTimeout(5);

		Map<String, TransactionAttribute> txmap = new HashMap<>();
		txmap.put("insert*", requiredTx);
		txmap.put("save*", requiredTx);
		txmap.put("add*", requiredTx);
		txmap.put("update*", requiredTx);
		txmap.put("delete*", requiredTx);
		txmap.put("get*", readOnlyTx);
		txmap.put("query*", readOnlyTx);
		source.setNameMap(txmap);

		return source;
	}

	/**
	 * 切面拦截规则 参数会自动从容器中注入
	 */
	@Bean
	public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor interceptor) {
		AspectJExpressionPointcutAdvisor pajp = new AspectJExpressionPointcutAdvisor();
		pajp.setAdvice(interceptor);
		pajp.setExpression(EXPRE);
		return pajp;
	}

	/**
	 * 事务拦截器
	 * 
	 * @param tx
	 * @return
	 */
	@Bean("interceptor")
	TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx) {
		return new TransactionInterceptor(tx, transactionAttributeSource());
	}

}
